const express = require('express');
const {createProxyMiddleware} = require('http-proxy-middleware');
const Datastore = require('nedb');
const cors = require('cors');

const app = express();
const config = require('./config/index.js');
//服务端口 目标API的基础URL 数据文件路径
const {PORT, TARGET_API, DB_PATH} = config;
// 创建一个新的Datastore实例并加载/保存到datafile.db
const db = new Datastore({filename: DB_PATH, autoload: true});
const crypto = require('crypto');
const querystring = require('querystring');

//添加数据库索引
/*db.ensureIndex({fieldName: 'path', unique: true}, (err) => {
    if (err) {
        console.error('索引创建失败', err);
    }
});*/

//运行跨域
// const whitelist = ['http://localhost:8000']
const corsOptions = {
    origin: function (origin, callback) {
        callback(null, true)
    },
    credentials: true,
}
app.use(cors(corsOptions));

// 解析 application/json
app.use(express.json({ limit: '10mb' })); // 设置为10MB
// 解析 application/x-www-form-urlencoded
app.use(express.urlencoded({ limit: '10mb', extended: true })); // 同样设置为10MB
// 检查路径是否存在于数据库中

function checkPathInDb(path, callback) {
    db.findOne({path}, (err, doc) => {
        if (err) return callback(err);
        callback(null, doc);
    });
}

// 将新的路径和响应保存到数据库
function savePathToDb(path, response, state, callback) {
    db.insert({path, response, state}, (err, newDoc) => {
        if (typeof callback === 'function') {
            callback(err, newDoc);
        }
    });
}

//计算对象的hash值
function generateObjectHash(obj) {
    // 将对象转换为 JSON 字符串，按属性名排序
    const jsonString = JSON.stringify(obj, (key, value) => {
        if (typeof value === 'object' && value !== null) {
            return Object.keys(value).sort().reduce((sortedObj, key) => {
                sortedObj[key] = value[key];
                return sortedObj;
            }, {});
        }
        return value;
    });

    // 创建一个 MD5 哈希对象
    const hash = crypto.createHash('md5');

    // 更新哈希对象的内容
    hash.update(jsonString);

    // 计算并返回哈希值
    return hash.digest('hex');
}

//查询


// 创建一个新的路径和响应
app.post('/sys/api', (req, res) => {
    const {path, response, state = false} = req.body;
    if (!path || !response) {
        return res.status(400).send({
            code: 400,
            message: 'Path and response are required'
        });
    }

    savePathToDb(path, response, state, (err, newDoc) => {
        if (err) {
            return res.status(500).send({
                code: 500,
                message: 'Failed to save to database'
            });
        }
        res.status(200).send({code: 0, data: true});
    });
});

// 获取所有路径和响应
app.get('/sys/api', (req, res) => {
    db.find({}, (err, docs) => {
        if (err) return res.status(500).send({
            code: 500,
            message: 'Failed to fetch data from database'
        });
        res.json(docs);
    });
});

// 分页获取所有路径和响应
app.post('/sys/page', (req, res) => {
    // 查询路径|当前页码，默认为1|每页显示的记录数，默认为10
    const {path, page = 1, limit = 10} = req.body;
    const skip = (page - 1) * limit; // 计算跳过的记录数
    // 创建正则表达式，支持模糊查询,不区分大小写
    const query = path ? {path: new RegExp(path, 'i')} : {};
    db.find(query).skip(skip).limit(limit).exec((err, docs) => {
        if (err) {
            return res.status(500).send({
                code: 500,
                message: 'Database error'
            });
        }

        // 计算总记录数
        db.count(query, (err, count) => {
            if (err) {
                return res.status(500).send({
                    code: 500,
                    message: 'Database error'
                });
            }
            res.json({
                code: 0,
                total: count,
                data: docs
            });
        });
    });
});

// 更新特定路径的响应
app.post('/sys/update', (req, res) => {
    const {path, response, state = false} = req.body;
    if (!response) {
        return res.status(400).send({
            code: 400,
            message: 'Response is required'
        });
    }

    db.update({path}, {$set: {response, state}}, {}, (err, numReplaced) => {
        if (err) return res.status(500).send({
            code: 500,
            message: 'Failed to update data in database'
        });
        if (numReplaced === 0) {
            return res.status(404)
                .send({
                    code: 404,
                    message: 'Path not found'
                });
        }
        res.send({
            code: 0,
            message: 'Data updated successfully'
        });
    });
});

// 删除特定路径的响应
app.post('/sys/delete', (req, res) => {
    db.remove(req.body, {}, (err, numRemoved) => {
        if (err) {
            return res.status(500).send({
                code: 500,
                message: 'Failed to delete data from database'
            });
        }
        if (numRemoved === 0) {
            return res.status(404).send({
                code: 404,
                message: 'Path not found'
            });
        }
        res.send({
            code: 0,
            data: true,
            message: 'Data deleted successfully'
        });
    });
});

// 获取特定路径的响应
app.post('/sys/config', (req, res) => {
    const {prop, value,} = req.body;
    if (value !== undefined) {
        config[prop] = value;
    }
    res.json({
        code: 0,
        data: config[prop],
    });
});


// 定义一个中间件来处理所有请求
app.use((req, res, next) => {
    const path = config.STRICT_MATCH ? req.originalUrl : req.path;

    console.log(req.originalUrl, req.path)

    // 查询路径是否在数据库中
    checkPathInDb(path, (err, doc) => {
        if (err) return next(err);

        if (doc) {
            // 如果当前的接口是启用状态.直接返回
            if (doc.state) {
                console.log('Mock:', req.method, path)
                res.send(JSON.parse(doc.response));
            } else {
                next();
            }

        } else {
            // 否则，继续处理请求（代理到目标服务器）
            next();
        }
    });
});


// 对于其他所有请求，我们使用代理中间件转发到目标API
app.use('/', createProxyMiddleware({
    target: TARGET_API,
    changeOrigin: true, // 更改主机头为目标URL
    timeout: 60000, // 设置超时时间为60秒
    // logLevel: 'debug',
    onProxyReq: (proxyReq, req, res) => {
        console.log('转发:', req.method, req.originalUrl)
        // 设置请求体  || !Object.keys(req.body).length
        if (req.body && req.method === 'POST') {
            const writeBody = (bodyData) => {
                proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData));
                proxyReq.write(bodyData);
            };
            const contentType = proxyReq.getHeader('Content-Type');
            if(typeof contentType === 'string'){
                if (contentType.toString().includes('application/json')) {
                    writeBody(JSON.stringify(req.body));
                }
                if (contentType.toString().includes('application/x-www-form-urlencoded')) {
                    writeBody(querystring.stringify(req.body));
                }
            }

        }
    },
    onProxyRes: (proxyRes, req, res) => {
        let bodyChunks = [];
        proxyRes.on('data', chunk => {
            bodyChunks.push(chunk);
        });

        proxyRes.on('end', () => {
            try {
                const responseBody = Buffer.concat(bodyChunks).toString('utf8');
                // console.log('收到数据:', req.originalUrl, responseBody);
                if (config.AUTO_SAVE) {
                    savePathToDb(config.STRICT_MATCH ? req.originalUrl : req.path, responseBody, true, (err) => {
                        if (err) console.error('保存接口数据失败:', err);
                    });
                }
            } catch (e) {
                console.error('响应数据处理异常:', e);
            }
        });
    },
    error: (err, req, res) => {
        console.error('代理异常:', err);
        res.status(500).send({error: '代理请求失败'});
    },
}));


// 启动服务器
app.listen(PORT, () => {
    console.log(`Server is running on port ${PORT}`);
});
